# coding=utf-8
from os.path import join


class EmrClusterProvision(object):
    def __init__(self, master_type='m4.large', instance_type='m4.large', instance_count=1, driver_memory='2500m', executor_memory='2500m', bootstrap_script=None, python_version="3"):
        self._build_default()
        configurations_node = self._find_by_node(self.configurations, 'Classification', 'spark-defaults')
        configurations_node['Properties']['spark.executor.memory'] = executor_memory
        configurations_node['Properties']['spark.driver.memory'] = driver_memory
        if bootstrap_script:
            bootstrapActions_node = self._find_by_node(self.bootstrapActions, 'Name', 'Custom action')
            bootstrapActions_node['ScriptBootstrapAction']['Path'] = join('s3://pt-emr-common', 'SourceCode', bootstrap_script)
        else:
            self.bootstrapActions = []

        masterInstance_node = self._find_by_node(self.instances['InstanceGroups'], 'Name', 'Master1')
        workerInstance_node = self._find_by_node(self.instances['InstanceGroups'], 'Name', 'Core2')
        masterInstance_node["InstanceType"] = master_type
        workerInstance_node["InstanceType"] = instance_type
        workerInstance_node["InstanceCount"] = instance_count
        if python_version == "3":
            self.use_python3()

    @staticmethod
    def _find_by_node(lst, prop_name, prop_value):
        for item in lst:
            if item[prop_name] == prop_value:
                return item
        raise KeyError("prop_name %s not found..." % prop_name)

    def use_python3(self):
        self.configurations.append({
                "Classification": "spark-env",
                "Configurations": [
                    {
                        "Classification": "export",
                        "Properties": {
                            "PYSPARK_PYTHON": "/usr/bin/python3"
                        }
                    }
                ]
            })

    def append_steps(self, steps):
        self.steps += [step.f() for step in steps]

    def _build_default(self):
        self.releaseLabel = 'emr-5.23.0'
        self.instances = {
            # 'MasterInstanceType': 'c4.large',
            # 'SlaveInstanceType': 'm4.large',
            # 'InstanceCount': 2,
            'InstanceGroups': [
                {
                    'Name': 'Master1',
                    'Market': 'ON_DEMAND',
                    'InstanceRole': 'MASTER',
                    # 'BidPrice': 'string',
                    'InstanceType': 'm4.large',
                    'InstanceCount': 1,
                    # 'Configurations': [
                    #     {
                    #         'Classification': 'string',
                    #         'Configurations': {'... recursive ...'},
                    #         'Properties': {
                    #             'string': 'string'
                    #         }
                    #     },
                    # ],
                    'EbsConfiguration': {
                        'EbsBlockDeviceConfigs': [
                            {
                                'VolumeSpecification': {
                                    'VolumeType': 'gp2',
                                    # 'Iops': 123,
                                    'SizeInGB': 32
                                },
                                'VolumesPerInstance': 1
                            },
                        ],
                        # 'EbsOptimized': True|False
                    },
                    # 'AutoScalingPolicy': {
                    #     'Constraints': {
                    #         'MinCapacity': 123,
                    #         'MaxCapacity': 123
                    #     },
                    #     'Rules': [
                    #         {
                    #             'Name': 'string',
                    #             'Description': 'string',
                    #             'Action': {
                    #                 'Market': 'ON_DEMAND'|'SPOT',
                    #                 'SimpleScalingPolicyConfiguration': {
                    #                     'AdjustmentType': 'CHANGE_IN_CAPACITY'|'PERCENT_CHANGE_IN_CAPACITY'|'EXACT_CAPACITY',
                    #                     'ScalingAdjustment': 123,
                    #                     'CoolDown': 123
                    #                 }
                    #             },
                    #             'Trigger': {
                    #                 'CloudWatchAlarmDefinition': {
                    #                     'ComparisonOperator': 'GREATER_THAN_OR_EQUAL'|'GREATER_THAN'|'LESS_THAN'|'LESS_THAN_OR_EQUAL',
                    #                     'EvaluationPeriods': 123,
                    #                     'MetricName': 'string',
                    #                     'Namespace': 'string',
                    #                     'Period': 123,
                    #                     'Statistic': 'SAMPLE_COUNT'|'AVERAGE'|'SUM'|'MINIMUM'|'MAXIMUM',
                    #                     'Threshold': 123.0,
                    #                     'Unit': 'NONE'|'SECONDS'|'MICRO_SECONDS'|'MILLI_SECONDS'|'BYTES'|'KILO_BYTES'|'MEGA_BYTES'|'GIGA_BYTES'|'TERA_BYTES'|'BITS'|'KILO_BITS'|'MEGA_BITS'|'GIGA_BITS'|'TERA_BITS'|'PERCENT'|'COUNT'|'BYTES_PER_SECOND'|'KILO_BYTES_PER_SECOND'|'MEGA_BYTES_PER_SECOND'|'GIGA_BYTES_PER_SECOND'|'TERA_BYTES_PER_SECOND'|'BITS_PER_SECOND'|'KILO_BITS_PER_SECOND'|'MEGA_BITS_PER_SECOND'|'GIGA_BITS_PER_SECOND'|'TERA_BITS_PER_SECOND'|'COUNT_PER_SECOND',
                    #                     'Dimensions': [
                    #                         {
                    #                             'Key': 'string',
                    #                             'Value': 'string'
                    #                         },
                    #                     ]
                    #                 }
                    #             }
                    #         },
                    #     ]
                    # }
                },
                {
                    'Name': 'Core2',
                    'Market': 'ON_DEMAND',
                    'InstanceRole': 'CORE',
                    # 'BidPrice': 'string',
                    'InstanceType': 'm4.large',
                    'InstanceCount': 1,
                    # 'Configurations': [
                    #     {
                    #         'Classification': 'string',
                    #         'Configurations': {'... recursive ...'},
                    #         'Properties': {
                    #             'string': 'string'
                    #         }
                    #     },
                    # ],
                    'EbsConfiguration': {
                        'EbsBlockDeviceConfigs': [
                            {
                                'VolumeSpecification': {
                                    'VolumeType': 'gp2',
                                    # 'Iops': 123,
                                    'SizeInGB': 32
                                },
                                'VolumesPerInstance': 1
                            },
                        ],
                        # 'EbsOptimized': True|False
                    },
                }
            ],
            # 'InstanceFleets': [
            #     {
            #         'Name': 'string',
            #         'InstanceFleetType': 'MASTER'|'CORE'|'TASK',
            #         'TargetOnDemandCapacity': 123,
            #         'TargetSpotCapacity': 123,
            #         'InstanceTypeConfigs': [
            #             {
            #                 'InstanceType': 'string',
            #                 'WeightedCapacity': 123,
            #                 'BidPrice': 'string',
            #                 'BidPriceAsPercentageOfOnDemandPrice': 123.0,
            #                 'EbsConfiguration': {
            #                     'EbsBlockDeviceConfigs': [
            #                         {
            #                             'VolumeSpecification': {
            #                                 'VolumeType': 'string',
            #                                 'Iops': 123,
            #                                 'SizeInGB': 123
            #                             },
            #                             'VolumesPerInstance': 123
            #                         },
            #                     ],
            #                     'EbsOptimized': True|False
            #                 },
            #                 'Configurations': [
            #                     {
            #                         'Classification': 'string',
            #                         'Configurations': {'... recursive ...'},
            #                         'Properties': {
            #                             'string': 'string'
            #                         }
            #                     },
            #                 ]
            #             },
            #         ],
            #         'LaunchSpecifications': {
            #             'SpotSpecification': {
            #                 'TimeoutDurationMinutes': 123,
            #                 'TimeoutAction': 'SWITCH_TO_ON_DEMAND'|'TERMINATE_CLUSTER',
            #                 'BlockDurationMinutes': 123,
            #                 'AllocationStrategy': 'capacity-optimized'
            #             },
            #             'OnDemandSpecification': {
            #                 'AllocationStrategy': 'lowest-price'
            #             }
            #         }
            #     },
            # ],
            'Ec2KeyName': 'pt-admin-ohio',
            # 'Placement': {
            #     'AvailabilityZone': 'us-east-2',
            #     'AvailabilityZones': [
            #         'string',
            #     ]
            # },
            'KeepJobFlowAliveWhenNoSteps': False,
            'TerminationProtected': True,
            # 'HadoopVersion': 'string',
            'Ec2SubnetId': 'subnet-0c2273e004b8a400f',
            # 'Ec2SubnetIds': [
            #     'string',
            # ],
            'EmrManagedMasterSecurityGroup': 'sg-0de0845e4d8c9b44c',
            'EmrManagedSlaveSecurityGroup': 'sg-0cbc8bb52f4bc3d34',
            'ServiceAccessSecurityGroup': 'sg-03f78c8a4e52eee2a',
            # 'AdditionalMasterSecurityGroups': [
            #     'string',
            # ],
            # 'AdditionalSlaveSecurityGroups': [
            #     'string',
            # ]
        }
        self.steps = [
            {
                'Name': 'Setup Hadoop Debugging',
                'ActionOnFailure': 'TERMINATE_CLUSTER',
                'HadoopJarStep': {
                    'Jar': 'command-runner.jar',
                    'Args': ['state-pusher-script']
                }
            },
        ]
        self.bootstrapActions = [
            {
                'Name': 'Custom action',
                'ScriptBootstrapAction': {
                    'Path': 's3://pt-emr-common/SourceCode/launch_cluster_emr_bootstrap_shutdown.sh',
                    # 'Args': [
                    #     'string',
                    # ]
                }
            },
        ]
        self.applications = [
            {
                'Name': 'Spark',
                # 'Version': 'v1.0',
            },
        ]
        self.configurations = [
            {
                'Classification': 'spark-defaults',
                'Properties': {
                    'spark.executor.memory': '2500m',
                    'spark.driver.memory': '2500m'
                }
            },
            {
                'Classification': 'spark',
                'Properties': {
                    'maximizeResourceAllocation': 'true'
                }
            },
        ]
        self.visibleToAllUsers = True
        self.jobFlowRole = 'EMR_EC2_DefaultRole'
        self.serviceRole = 'EMR_DefaultRole'
